import { onUnmounted, onMounted, ref } from 'vue'
import type { Ref } from 'vue'
import { getUuid, download } from '@/utils'
import eventBus from '@/utils/bus'
import { useMessage } from '@/hooks'
import localforageCache from '@/utils/localforage'
import html2canvas from 'html2canvas'
import {
  CompContextMenuEnum,
  DragKeyEnum,
  ToolBarEnum,
  BaseEventEnum,
  KeyEventEnum,
  PanelJsonKeysEnum,
  MonacoEditEnum
} from '@/enums'
import type { Router } from 'vue-router'
import { JSONParse, JSONStringify } from 'wft-utils'

export function usePanelAction(panelJson: Ref<TPanel>, emits: Function, router: Router) {
  let curCopyComp = ref<TComp | null>(null)
  let resizeObserver: ResizeObserver | null = null

  // 移入到目标容器松开鼠标
  const compDrop = (event: DragEvent) => {
    if(!event.dataTransfer?.getData(DragKeyEnum.DRAG_DATA_KEY)) return
    let dragData = JSONParse(event.dataTransfer?.getData('dragData'))
    let curCom = JSONParse(JSONStringify(dragData.curCom))
    curCom.id = getUuid() as string
    const workspacePanelEditContainer = document.querySelector('#workspace-panel-edit')!
    const { left, top, width, height } = <DOMRect>workspacePanelEditContainer.getBoundingClientRect()
    curCom.grid.top = Math.floor(event.clientY - top - dragData.offsetY)
    curCom.grid.left = Math.floor(event.clientX - left - dragData.offsetX)
    curCom.resizeGrid.top = ((curCom.grid.top / height) * 100).toFixed(0) + '%'
    curCom.resizeGrid.left = ((curCom.grid.left / width) * 100).toFixed(0) + '%'
    curCom.resizeGrid.width = ((curCom.grid.width / width) * 100).toFixed(0) + '%'
    curCom.resizeGrid.height = ((curCom.grid.height / height) * 100).toFixed(0) + '%'
    curCom.config.isActive = true
    panelJson.value.comps?.forEach(item => item.config.isActive = false)
    panelJson.value.comps?.push(curCom)
    emits('compActiveChange', curCom)
    if(event.dataTransfer?.getData('dragData')) {
      event.dataTransfer.clearData('dragData')
    }
  }

  // 点击图层
  const layerItemChange = (index: number) => {
    if(!panelJson.value.comps?.length) return
    for(let i = 0; i < panelJson.value.comps?.length; i++) {
      if(i == index) {
        panelJson.value.comps[i].config.isActive = !panelJson.value.comps[index].config.isActive
      } else {
        panelJson.value.comps[i].config.isActive = false
      }
    }
  }

  // 粘贴
  const panelPaste = (event?: MouseEvent) => {
    if(curCopyComp.value) {
      let pushComp = JSONParse(JSONStringify(curCopyComp.value))
      const { left, top, width, height } = document.querySelector('#workspace-panel-edit')?.getBoundingClientRect() as DOMRect
      if(event) {
        pushComp.grid.left = event.clientX - left
        pushComp.grid.top = event.clientY - top
      } else {
        pushComp.grid.left = pushComp.grid.left + 40
        pushComp.grid.top = pushComp.grid.top + 40
      }
      pushComp.resizeGrid.left = ((pushComp.grid.left / width) * 100).toFixed(0) + '%'
      pushComp.resizeGrid.top = ((pushComp.grid.top / height) * 100).toFixed(0) + '%'
      pushComp.id = getUuid()
      panelJson.value.comps?.push(pushComp)
      curCopyComp.value = JSONParse(JSONStringify(pushComp))
    }
  }

  // 清空剪切板
  const clearCut = () => {
    curCopyComp.value = null
  }

  // 清空画板
  const clearPanel = () => {
    panelJson.value.comps = []
  }

  onMounted(() => {
    document.addEventListener(BaseEventEnum.ON_MOUSE_DOWN, mousedownHandler)
    window.addEventListener(MonacoEditEnum.EDIT_PANEL_JSON, editPanelJsonHandler)
    if (!resizeObserver) {
      // 等收缩完之后只计算一次，会出现直接移过去、宽度直接变化，很僵硬
      // 一直计算体验更好，肯定有牺牲性能为代价
      resizeObserver = new ResizeObserver(() => {
        if(!panelJson.value.comps?.length) return
        const { width } = document.querySelector('#workspace-panel-edit')?.getBoundingClientRect() as DOMRect
        panelJson.value.comps?.forEach((item: TComp) => {
          item.grid.left = Math.floor(width * (parseInt(item.resizeGrid.left.slice(0, -1)) / 100))
          item.grid.width = Math.floor(width * (parseInt(item.resizeGrid.width.slice(0, -1)) / 100))
        })
      })
      resizeObserver.observe((document.getElementById('workspace-panel-edit') as HTMLElement))
    }
  })

  eventBus.on('*', wildcardHandler)
  eventBus.on(ToolBarEnum.PANEL_IMPORT, panelImportHandler)
  onUnmounted(() => {
    eventBus.off('*', wildcardHandler);
    eventBus.off(ToolBarEnum.PANEL_IMPORT, panelImportHandler);
    document.removeEventListener(BaseEventEnum.ON_MOUSE_DOWN, mousedownHandler);
    window.removeEventListener(MonacoEditEnum.EDIT_PANEL_JSON, editPanelJsonHandler);
    document.removeEventListener(KeyEventEnum.ON_KEY_DOWN, keydownHandler);
    (resizeObserver as ResizeObserver).disconnect();
    resizeObserver = null
  })

  function wildcardHandler(mitterType: string, compId?: string) {
    const map: { [key: string]: any } = {
      [CompContextMenuEnum.LAYER_TOPPING]: layerToppingHandler,
      [CompContextMenuEnum.LAYER_BOTTOMING]: layerBottomingHandler,
      [CompContextMenuEnum.LAYER_MOVE_UP]: layerMoveupHandler,
      [CompContextMenuEnum.LAYER_MOVE_DOWN]: layerMovedownHandler,
      [CompContextMenuEnum.LAYER_DELETE]: layerDeleteHandler,
      [ToolBarEnum.PANEL_EXPORT]: panelExportHandler,
      [ToolBarEnum.PREVIEW_PANEL]: previewPanelHandler,
      [ToolBarEnum.ONLINE_EDIT]: onlineEditHandler,
      [CompContextMenuEnum.COMP_COPY]: compCopyHandler,
      [CompContextMenuEnum.COMP_CUT]: compCutHandler,
      [ToolBarEnum.PANEL_TO_PNG]: panel2pngHandler,
      [ToolBarEnum.PANEL_PUBLISH]: panelPublishHandler,
    }
    if(map[mitterType] && typeof map[mitterType] === 'function') {
      if(compId) {
        const index = panelJson.value.comps?.findIndex(item => item.id == compId)
        map[mitterType](index)
      } else {
        map[mitterType]()
      }
    }
  }

  // 置顶
  function layerToppingHandler(curIndex: number) {
    if(!panelJson.value.comps?.length) return
    if(curIndex == 0) {
      return
    }
    panelJson.value.comps?.unshift(...panelJson.value.comps.splice(curIndex, 1))
  }

  // 置底
  function layerBottomingHandler(curIndex: number) {
    if(!panelJson.value.comps?.length) return
    if(curIndex == panelJson.value.comps?.length - 1) {
      return
    }
    panelJson.value.comps?.push(...panelJson.value.comps.splice(curIndex, 1))
  }

  // 上移
  function layerMoveupHandler(curIndex: number) {
    if(!panelJson.value.comps?.length) return
    if(curIndex == 0) {
      return
    }
    panelJson.value.comps?.splice(curIndex - 1, 0, ...panelJson.value.comps.splice(curIndex, 1))
  }

  // 下移
  function layerMovedownHandler(curIndex: number) {
    if(!panelJson.value.comps?.length) return
    if(curIndex == panelJson.value.comps?.length - 1) {
      return
    }
    panelJson.value.comps?.splice(curIndex + 1, 0, ...panelJson.value.comps.splice(curIndex, 1))
  }

  // 删除
  function layerDeleteHandler(curIndex: number) {
    panelJson.value.comps?.splice(curIndex, 1)
  }

  // 导出json
  function panelExportHandler() {
    const json = JSONStringify(panelJson.value)
    const link = document.createElement('a')
    const URL = window.URL || window.webkitURL;
    link.href = URL.createObjectURL(new Blob([json]))
    link.download = `${panelJson.value.container.title}.json`
    document.body.appendChild(link)
    link.click()
    document.body.removeChild(link)
  }

  // 导入json
  function panelImportHandler(file: Blob) {
    const fr = new FileReader()
    fr.readAsText(file)
    fr.onload = () => {
      try {
        let data = JSONParse(fr.result as string)
        if(data && data.container) {
          if(data.comps?.length) {
            panelJson.value = data
            emits('containerConfig', panelJson.value.container)
          } else {
            useMessage().warning('您选择的是空页面!')
          }
        } else {
          useMessage().error('文件解析错误，请确保为json文件且格式数据正确!')
        }
      } catch(e) {
        useMessage().error('文件解析错误，请确保为json文件且格式数据正确!')
      }
    }
  }

  // 预览
  function previewPanelHandler() {
    let curPanelJson = JSONParse(JSONStringify(panelJson.value))
    localforageCache.set(PanelJsonKeysEnum.CUR_PREVIEW_PANEL_JSON_KEY, curPanelJson).then(() => {
      const previewPanelUrl = router.resolve({ path: '/preview' })
      window.open(previewPanelUrl.href, '_blank')
    }).catch((e: any) => console.log(e, '预览出错了~~'))
  }

  // 在线编辑
  async function onlineEditHandler() {
    let curPanelJson = JSONParse(JSONStringify(panelJson.value))
    await localforageCache.set(PanelJsonKeysEnum.CUR_PREVIEW_PANEL_JSON_KEY, curPanelJson)
    let editUrl = router.resolve({ path: '/edit' })
    window.open(editUrl.href, '_blank')
  }

  // 在线编辑保存
  function editPanelJsonHandler(e: any) {
    panelJson.value = e.detail
    emits('containerConfig', panelJson.value.container)
  }

  // 复制
  function compCopyHandler(index: number) {
    curCopyComp.value = JSONParse(JSONStringify(panelJson.value.comps?.[index] || null))
  }

  // 剪切
  function compCutHandler(index: number) {
    curCopyComp.value = JSONParse(JSONStringify(panelJson.value.comps?.[index] || null))
    panelJson.value.comps?.splice(index, 1)
  }

  // 画板保存为图片
  function panel2pngHandler() {
    html2canvas(document.getElementById('workspace-panel-edit') as HTMLElement).then(canvas => {
      canvas.toBlob((blob: Blob | null) => {
        download(blob, `${panelJson.value.container.title}.png`)
      }, "image/png")
    })
  }

  // 发布
  function panelPublishHandler() {
    const curPublishPageJson = JSONParse(JSONStringify(panelJson.value))
    curPublishPageJson.id = getUuid()
    // ...
  }

  // 鼠标按下
  function mousedownHandler(event: MouseEvent) {
    if(document.querySelector('#workspace-panel-edit')?.contains(<Node>event.target)) {
      document.addEventListener(KeyEventEnum.ON_KEY_DOWN, keydownHandler)
    } else {
      document.removeEventListener(KeyEventEnum.ON_KEY_DOWN, keydownHandler)
    }
  }

  // 键盘按下
  function keydownHandler(event: KeyboardEvent) {
    if(!event.ctrlKey) return
    if(event.key == 'c') {
      let curActiveComp: TComp | undefined = panelJson.value.comps?.find(item => item.config.isActive)
      if(curActiveComp) {
        curCopyComp.value = JSONParse(JSONStringify(curActiveComp))
      }
    } else if(event.key == 'x') {
      let curActiveCompIndex: number | undefined = panelJson.value.comps?.findIndex(item => item.config.isActive)
      if(curActiveCompIndex !== undefined && curActiveCompIndex >= 0) {
        let spliceComp = panelJson.value.comps?.splice(curActiveCompIndex, 1)
        if(spliceComp && spliceComp.length) {
          curCopyComp.value = JSONParse(JSONStringify(spliceComp[0]))
        }
      }
    } else if(event.key == 'v') {
      panelPaste()
    }
  }

  return { compDrop, layerItemChange, panelPaste, clearCut, clearPanel }
}